home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / t_sys5 / unixcpio.gz / unixnet.cpio / ax_mbx.c < prev    next >
C/C++ Source or Header  |  1994-07-11  |  48KB  |  1,914 lines

  1. /* Ok, I admit it... what I've done here is a mortal sin, but the XOBBS module
  2.    for ax_mbx.c is so different from the W9NK mailbox, and I hate forcing folks
  3.    to move files around before running a make, so here it is... the two cat'ed
  4.    together with an "if XOBBS ... else ... endif" wrapper... sick, but it
  5.    works...   Bdale */
  6.  
  7. #ifdef XOBBS
  8. /* XOBBS.C  module to link NET thru IPC message queues to the XOBBS mailbox. */
  9. /* Jim Durham, W2XO, 1-5-89 */
  10. /* requires a call to axchk() to be inserted in the main commutator loop of
  11.     the net main.c code */
  12.  
  13. #include <stdio.h>
  14. #include "global.h"
  15. #include "config.h"
  16. #include "mbuf.h"
  17. #include "ax25.h"
  18. #include "timer.h"
  19. #include "lapb.h"
  20. #include "cmdparse.h"
  21. #include "iface.h"
  22. #include <fcntl.h>
  23. #include <signal.h>
  24. #include <sys/types.h>
  25. #include <sys/ipc.h>
  26. #include <sys/msg.h>
  27. #include "netrom.h"
  28. #include "nr4.h"
  29. #include "ax_mbx.h"
  30. #ifdef    UNIX
  31. #undef    toupper
  32. #undef    tolower
  33. #include <memory.h>
  34. #include <string.h>
  35. #endif
  36.  
  37. #ifdef    BSD
  38. char *sprintf();
  39. #endif
  40.  
  41. /*#define DEBUG       1*/
  42.  
  43. void fwdxmit();
  44. void fwdrecv();
  45. void fwdstate();
  46. void axbbs_xmit();
  47. char xogetc();
  48. static char conbuf[10][10];        /*buffers used in getcon() and fwdcon()*/
  49. int conindex,conchar;
  50. int fwdflag;            /*flag to do various forwarding tasks*/
  51. int pid;
  52. int fwdbbsstate = NOCON;    /* con/discon state of forwarding bbs process */
  53. int smsgqid;            /* send message queue (from viewpoint of bbs) */
  54. int rmsgqid;            /* receive message queue (from viewpoint of bbs) */
  55. int scmsgqid;            /* send CONTROL message queue */
  56. int rcmsgqid;            /* receive CONTROL message queue */
  57. int lastindex;                  /*last bbs index used*/
  58. int nsend;
  59. int ax25mbox;
  60. char temp[128];
  61. char *bbsexe = "xobbs";        /*path to bbs executable*/
  62. struct  ax25_cb *bbscb;        /*forwarding bbs control block*/
  63. struct message  msg;
  64.  
  65. struct mboxsess * base = NULLMBS;  /*pointer to base of mailbox chain*/
  66. struct mboxsess fwdstruct;    /*forwarding session*/
  67.  
  68. #ifdef SID2
  69. extern struct ax25_addr bbscall;
  70. #endif
  71.  
  72. static struct mboxsess *
  73. newmbox()
  74. {
  75.     struct mboxsess * mbp ;
  76.  
  77.         if(base == NULLMBS){
  78.             base =(struct mboxsess *)malloc(sizeof(struct mboxsess));
  79.             base->next = NULLMBS;
  80.         initmbox(base);
  81.             return base;
  82.         }
  83.         else{
  84.         mbp = base;
  85.         while(mbp->next != NULLMBS)       /*go up the chain to the top*/
  86.             mbp = mbp->next;
  87.         mbp->next =(struct mboxsess *)malloc(sizeof(struct mboxsess));
  88.         mbp->next->next = NULLMBS;
  89.         initmbox(mbp->next);
  90.         return mbp->next;
  91.     }
  92. }
  93.  
  94. initmbox(mbp)
  95.     struct mboxsess * mbp;
  96. {
  97.     
  98.     mbp->bytes = 0;
  99.     mbp->gotbytes = 0;
  100.     mbp->mtxtptr = mbp->rmsgbuf.mtext;
  101. }
  102.  
  103. freembox(mbp)
  104.     struct mboxsess * mbp;
  105. {
  106.     struct mboxsess *p;
  107.     
  108.     if(mbp == base){            /*special case for base session*/
  109.         if(base->next != NULLMBS)/*if base is NOT the only session*/
  110.             base = base->next;   /*then make base point to next session*/
  111.         else
  112.             base = NULLMBS;     /*otherwise,just set base to NULLMBS*/
  113.         free(mbp);              /*free up the storage*/
  114.         return;                 /*and go away*/
  115.     }
  116.     p = base;
  117.     for(;;){
  118.         if(p->next == mbp){     /*if the next upward session is THE one*/
  119.             p->next = mbp->next; /*eliminate the next upward session*/
  120.             free(mbp);
  121.             return;
  122.         }
  123.         if(p->next == NULLMBS){ /*something is wrong here!*/
  124.             free(mbp);          /*try to fix it*/
  125.             return;
  126.         }
  127.         p = p->next;
  128.     }
  129. }
  130.     
  131.             
  132. axchk()        /* service any ax25 connections w2xo 9-1-88*/
  133. {
  134.     int rdcnt;
  135.     struct mbuf *bp;
  136.     struct mboxsess * mbp;
  137.     char *cp;
  138.     int testsize,size;
  139.     void axinit();
  140.     
  141. /* initialization code removed.  call to axinit() direct from main now. */
  142.     
  143.     if(base == NULLMBS)                       /*no mailboxes?..then leave*/
  144.         goto fcontchk;
  145.     mbp = base;                    /*point to the session base*/
  146.     while(mbp != NULLMBS){            /*and climb the session links*/
  147.         if(mbp->gotbytes < 1)            /*if we need input*/
  148.             if((mbp->gotbytes=msgrcv(smsgqid,&mbp->rmsgbuf,1024,(long)mbp->pid,
  149.                IPC_NOWAIT|0600)) < 1)        /*and there is none, ..punt*/
  150.                  goto contchk;
  151.             else                /*got input!*/
  152.                 mbp->mtxtptr = mbp->rmsgbuf.mtext; /*new message buffer, set to start*/
  153.  
  154.             testsize = min(mbp->bytes,mbp->cbadr.axbbscb->paclen+1);      /* get the minimum of the # */
  155.             size = min(testsize, mbp->gotbytes) + 1;       /* of bytes avail and paclen*/
  156.             bp = alloc_mbuf((int16)size);                  /* then min of avail and have*/
  157.             cp = bp->data;
  158.         if(mbp->proto == AX25){
  159.                 *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  160.                 bp->cnt =1;
  161.             }
  162.             else  bp->cnt = 0;
  163.             
  164.             while(bp->cnt < size && mbp->gotbytes){
  165.                 *cp++ = *mbp->mtxtptr++;
  166.                 bp->cnt++;
  167.                 mbp->gotbytes--;
  168.             }
  169.  
  170.         if(mbp->proto == AX25)
  171.             send_ax25(mbp->cbadr.axbbscb,bp);
  172.         else
  173.             send_nr4(mbp->cbadr.axnrcb,bp);
  174.                 /*now, check for control messages*/
  175.  
  176. contchk:    rdcnt=msgrcv(scmsgqid,&msg,1024,(long)mbp->pid,IPC_NOWAIT|0600);
  177. #ifdef DEBUG
  178.         if(rdcnt > 0) printf("net:Control Message received: rdcnt=%d\n",rdcnt);
  179. #endif
  180.             switch(rdcnt){
  181.                 case 0:     break;
  182.                 case -1:    /*perror("axchk002");*/
  183.                             break;
  184.                 default:    if(msg.mtext[0] == 'K'){
  185. #ifdef DEBUG
  186.                     printf("recbbs: K received\n");
  187. #endif
  188.                 kill(mbp->pid,9);
  189.                 wait(NULLCHAR);
  190.                 clearque(mbp->pid);
  191.                  if(mbp->proto == AX25)
  192.                      disc_ax25(mbp->cbadr.axbbscb);
  193.                  else
  194.                      disc_nr4(mbp->cbadr.axnrcb);
  195.  
  196.                 freembox(mbp);
  197.                             }/* if K */
  198.             }/* switch */
  199.         mbp = mbp->next;
  200.     }/*while loop*/
  201.  
  202. fcontchk:    chkfwd();            /*check the forwarder*/
  203. }
  204.  
  205. dombox(argc, argv)
  206. int argc ;
  207. char *argv[] ;
  208. {
  209.     if (argc < 2) {
  210.         domboxdisplay() ;
  211.         return 0 ;
  212.     }
  213.  
  214.     if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  215.         ax25mbox = 1 ;
  216.     else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  217.         ax25mbox = 0 ;
  218.     else if (argv[1][0] == '?')
  219.         printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
  220.     else
  221.         printf("usage: mbox [y|n|?]\n") ;
  222.  
  223.     return 0 ;
  224. }
  225.  
  226. static domboxdisplay()
  227. {
  228.  
  229.     struct mboxsess * mbp;
  230.     printf("Process-ID     &cb      Protocol      User\n") ;
  231.         mbp = base;    
  232.     while(mbp != NULLMBS){
  233.             printf("%-13d%-13x",mbp->pid,mbp->cbadr.axbbscb);             
  234.                 if(mbp->proto == AX25)
  235.                 printf("Ax25        %s\n",mbp->call);
  236.             else
  237.                 printf("Net/Rom     %s\n",mbp->call);
  238.             mbp = mbp->next;
  239.         }/*while loop*/
  240.     printf("\n\n");
  241.     printf("Forwarder State is: ");
  242.     switch(fwdflag){
  243.       case 0: printf("NOFWD\n");
  244.               break;
  245.       case 1: printf("SPAWNBBS\n");
  246.               break;
  247.       case 2: printf("DOCONNECT\n");
  248.               break;
  249.       case 3: printf("READXMIT\n");
  250.               break;
  251.       case 4: printf("GETCON\n");
  252.               break;
  253.       case 5: printf("CLEARCON\n");
  254.               break;
  255.       case 6: printf("WAITING\n");
  256.               break;
  257.       default: printf("UNDEFINED\n");
  258.               break;
  259.     }
  260. }
  261. /* Incoming mailbox session via ax.25 */
  262.  
  263.  
  264. /* * This is the ax25 receive upcall function
  265.  *it gathers incoming data and stuff it down the IPC queue to the proper BBS
  266.  */
  267.  
  268. void
  269. mbx_incom(axp,cnt)    
  270. struct ax25_cb *axp;
  271. int16 cnt;
  272. {
  273. #ifndef SID2
  274.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];    
  275.     void mbx_tx(), mbx_rx(), mbx_state();
  276.     int j;
  277.     struct mboxsess *mbp;
  278.     struct mbuf *bp;
  279.     struct mbuf *recv_ax25();
  280.     
  281.                 mbp =newmbox();        /*after this, this is a mailbox connection*/
  282.                         /* so, make a new mailbox session*/
  283.             axp->r_upcall = mbx_rx ;
  284.             axp->t_upcall = mbx_tx ;
  285.         axp->s_upcall = mbx_state;
  286.                 mbp->cbadr.axbbscb=axp;
  287.                 mbp->proto = AX25;
  288.                 mbp->bytes = 32;    /*jump start the upcall*/
  289.  
  290.         bp = recv_ax25(axp,cnt) ;    /* get the initial input */
  291.         free_p(bp) ;            /* and throw it away to avoid confusion */
  292.  
  293.  
  294.                 for(j=0;j<6;j++){               /*now, get incoming call letters*/
  295.                     arg1[j]=mbp->cbadr.axbbscb->addr.dest.call[j];
  296.                     arg1[j]=arg1[j] >> 1;
  297.                     arg1[j]=arg1[j] & (char)0x7f;
  298.                     if(arg1[j]==' ') arg1[j]='\0';
  299.                 }
  300.                 arg1[6]='\0';            /*terminate call letters*/
  301.             strcpy(mbp->call,arg1);   /*Copy call to session*/
  302.                 sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  303.                 sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  304.                 sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  305.                 sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  306.  
  307.                                            /*now, fork and exec the bbs*/
  308.                 if((pid=fork()) == 0){              /*if we are the child*/
  309.                     if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  310. #ifdef DEBUG
  311.                         printf("Bad exec on BBS\n");
  312. #endif
  313.                         exit(1);
  314.                     }
  315.                 }
  316.                 else                      /* parent process is still NET */
  317.                     mbp->pid=pid;         /* save pid of new baby*/
  318. #endif
  319. }    
  320.  
  321. void
  322. mbx_rx(axp,cnt)        /*w2xo  2-16-89  */
  323. struct ax25_cb *axp;        /* send chars down pipe to bbs */
  324. int16 cnt;
  325. {
  326.     struct mbuf *bp;
  327.     struct mbuf *recv_ax25();
  328.     struct mboxsess * mbp;
  329.  
  330.     
  331.     if(base == NULLMBS)
  332.         return;
  333.     mbp = base;
  334.     while(mbp != NULLMBS){
  335.     if(mbp->proto == AX25){
  336.             if(mbp->cbadr.axbbscb == axp){  /* match requested block? */
  337.                 if((bp = recv_ax25(axp,cnt)) == NULLBUF)  /*nothing there*/
  338.             continue;
  339.                 while(bp != NULLBUF){
  340.                     strncpy(msg.mtext,bp->data,bp->cnt);
  341.                     msg.mtype = (long)mbp->pid;
  342.                     if(msgsnd(rmsgqid,&msg,bp->cnt,0600) < 0)
  343.                         perror("axincoming");
  344.                     bp=free_mbuf(bp);   /*free the mbuf and get the next */
  345.                 }
  346.             } /* if matching axp */
  347.         }/*if ax25 */
  348.     mbp = mbp->next;
  349.     }/*while loop*/
  350. }
  351.  
  352. void
  353. mbx_tx(axp,cnt)
  354. struct ax25_cb *axp;
  355. int16 cnt;
  356. {
  357.     struct mboxsess * mbp;
  358.     if(base == NULLMBS)
  359.         return;                     /*no sessions*/
  360.     mbp = base;
  361.     while(mbp != NULLMBS){
  362.         if(mbp->cbadr.axbbscb == axp)
  363.             mbp->bytes = cnt;
  364.     mbp = mbp->next;
  365.     }
  366. }
  367.  
  368. void
  369. mbx_state(axp,old,new)        /*w2xo  3-23-89 */
  370. struct ax25_cb *axp;
  371. int old,new;
  372. {
  373. #ifdef SID2
  374.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];    
  375.     void mbx_tx(), mbx_rx(), mbx_state();
  376.     int j;
  377. #endif
  378.     struct mboxsess *mbp;
  379.  
  380.         switch(new){
  381.             case DISCONNECTED:
  382.            if((old == DISCONNECTED) || (old == DISCPENDING))
  383.                return;
  384.                 if(base == NULLMBS)
  385.                     break;
  386.             mbp = base;
  387.                 while(mbp != NULLMBS){
  388.                     if(axp == mbp->cbadr.axbbscb && mbp->proto == AX25){
  389.                         kill(mbp->pid,9);     /*kill bbs process*/
  390.                         wait(NULLCHAR);
  391.                         freembox(mbp);
  392.                         break; /* from while loop */
  393.                     } /*if*/
  394.                     mbp = mbp->next;
  395.                 }/*while loop*/
  396.                 break;   /*end of DISCONNECTED case*/
  397.                     
  398.             case CONNECTED:
  399. #ifdef SID2
  400.         if(old != DISCONNECTED)
  401.             return;
  402.             if(!calleq(axp,&bbscall)){ /*not for the mailbox*/
  403.             axp->s_upcall = NULLVFP;
  404.             return;
  405.             }
  406.     
  407.                 mbp =newmbox();        /*after this, this is a mailbox connection*/
  408.                         /* so, make a new mailbox session*/
  409.             axp->r_upcall = mbx_rx ;
  410.             axp->t_upcall = mbx_tx ;
  411.  
  412.                 mbp->cbadr.axbbscb=axp;
  413.                 mbp->proto = AX25;
  414.                 mbp->bytes = 32;    /*jump start the upcall*/
  415.  
  416.                 for(j=0;j<6;j++){               /*now, get incoming call letters*/
  417.                     arg1[j]=mbp->cbadr.axbbscb->addr.dest.call[j];
  418.                     arg1[j]=arg1[j] >> 1;
  419.                     arg1[j]=arg1[j] & (char)0x7f;
  420.                     if(arg1[j]==' ') arg1[j]='\0';
  421.                 }
  422.                 arg1[6]='\0';            /*terminate call letters*/
  423.             strcpy(mbp->call,arg1);   /*Copy call to session*/
  424.                 sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  425.                 sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  426.                 sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  427.                 sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  428.  
  429.                                            /*now, fork and exec the bbs*/
  430.                 if((pid=fork()) == 0){              /*if we are the child*/
  431.                     if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  432. #ifdef DEBUG
  433.                         printf("Bad exec on BBS\n");
  434. #endif
  435.                         exit(1);
  436.                     }
  437.                 }
  438.                 else                      /* parent process is still NET */
  439.                     mbp->pid=pid;         /* save pid of new baby*/
  440. #endif
  441.                 break;
  442.         }/* end of switch*/
  443. }/*end of routine*/
  444.  
  445.  
  446. /* Incoming mailbox session via net/rom */
  447.  
  448. void
  449. mbx_nr4incom(cb)
  450. register struct nr4cb *cb ;
  451. {
  452.     void mbx_nr4tx(), mbx_nr4rx(), mbx_nr4state() ;
  453.         char arg1[10],arg2[10],arg3[10],arg4[10],arg5[10];
  454.         struct mboxsess * mbp;
  455.     int j;
  456.         
  457.         mbp = newmbox();
  458.  
  459.     cb->r_upcall = mbx_nr4rx ;
  460.     cb->s_upcall = mbx_nr4state ;
  461.     cb->t_upcall = mbx_nr4tx ;
  462.  
  463.         mbp->cbadr.axnrcb = cb;
  464.         mbp->proto = NTRM;
  465.         mbp->bytes = 32;    /*jump start the upcall*/
  466.  
  467.         for(j=0;j<6;j++){               /*now, get incoming call letters*/
  468.             arg1[j]=mbp->cbadr.axnrcb->user.call[j];
  469.             arg1[j]=arg1[j] >> 1;
  470.             arg1[j]=arg1[j] & (char)0x7f;
  471.             if(arg1[j]==' ') arg1[j]='\0';
  472.         }
  473.         arg1[6]='\0';            /*terminate call letters*/
  474.     strcpy(mbp->call,arg1);  /*copy call to session*/
  475.  
  476.         sprintf(arg2,"%d\0",rmsgqid);   /*set up args telling what the*/
  477.         sprintf(arg3,"%d\0",smsgqid);   /*message ques are for the */
  478.         sprintf(arg4,"%d\0",rcmsgqid);   /*execed process*/
  479.         sprintf(arg5,"%d\0",scmsgqid);   /*execed process*/
  480.  
  481.                                          /*now, fork and exec the bbs*/
  482.         if((pid=fork()) == 0){              /*if we are the child*/
  483.             if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  484. #ifdef DEBUG
  485.                 printf("Bad exec on BBS\n");
  486. #endif
  487.                 exit(1);
  488.             }
  489.         }
  490.         else                            /* parent process is still NET */
  491.             mbp->pid=pid;         /* save pid of new baby*/
  492. }
  493.  
  494. /* receive upcall for net/rom */
  495. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  496. /* If the lines get too long, it arbitrarily breaks them. */
  497.  
  498. void mbx_nr4rx(cb,cnt)
  499. struct nr4cb *cb ;
  500. int16 cnt ;
  501. {
  502.     struct mbuf *bp;
  503.     struct mbuf *recv_ax25();
  504.     struct mboxsess * mbp;
  505.  
  506.  
  507.     
  508.     if(base == NULLMBS)
  509.         return;
  510.     mbp = base;
  511.     while(mbp != NULLMBS){
  512.     if(mbp->proto == NTRM){
  513.             if(mbp->cbadr.axnrcb == cb){  /* match requested block? */
  514.                 if((bp = recv_nr4(cb,cnt)) == NULLBUF)  /*nothing there*/
  515.             continue;
  516.                 while(bp != NULLBUF){
  517.                     strncpy(msg.mtext,bp->data,bp->cnt);
  518.                     msg.mtype = (long)mbp->pid;
  519.                     if(msgsnd(rmsgqid,&msg,bp->cnt,0600) < 0)
  520.                         perror("nrincoming");
  521.                     bp=free_mbuf(bp);   /*free the mbuf and get the next */
  522.                 }
  523.             } /* if matching axp */
  524.         } /* if netrom */
  525.     mbp = mbp->next;
  526.     } /*while loop*/
  527. }
  528.  
  529. void
  530. mbx_nr4tx(cb,cnt)
  531. struct nr4cb *cb;
  532. int16 cnt;
  533. {
  534.     struct mboxsess *mbp;
  535.     if(base == NULLMBS)
  536.         return;
  537.     mbp = base;
  538.     while(mbp != NULLMBS){
  539.         if(mbp->cbadr.axnrcb == cb)
  540.             mbp->bytes = cnt;
  541.         mbp = mbp->next;
  542.     }
  543. }
  544.  
  545. /* state upcall for net/rom */
  546. void mbx_nr4state(cb,old,new)
  547. struct nr4cb *cb ;
  548. int old, new ;
  549. {
  550.     struct mboxsess * mbp;
  551.  
  552.     switch(new){
  553.         case DISCONNECTED:
  554.             if(base == NULLMBS)
  555.                 return;
  556.             mbp = base;
  557.             while(mbp != NULLMBS){
  558.                 if(cb == mbp->cbadr.axnrcb){
  559.                     kill(mbp->pid,9);     /*kill bbs process*/
  560.                     wait(NULLCHAR);
  561.                     freembox(mbp);
  562.                     break; /* from for loop */
  563.                 }
  564.             mbp = mbp->next;
  565.             }/*end of while loop*/
  566.         break;   /*end of DISCONNECTED case*/
  567.                     
  568.         case CONNECTED:
  569.             break; /* end of connected case*/
  570.     }/* end of switch*/
  571. }/*end of routine*/
  572.  
  573. indexx(s,t)
  574. char s[],t[];
  575. {
  576.     int i,j,k;
  577.     
  578.     for(i=0;s[i]!= '\0'; i++){
  579.         for(j=i,k=0;t[k]!='\0' && s[j] == t[k]; j++,k++)
  580.             ;
  581.         if(t[k] == '\0')
  582.             return(i);
  583.     }
  584.     return(-1);
  585. }
  586.  
  587.  
  588. chkfwd()                /* check forwarding and take appropriate*/
  589. {                    /* actions*/
  590.     int gotbytes;
  591.  
  592.     if(fwdbbsstate==WAIT)
  593.         return;
  594.     switch(fwdflag){
  595.         case NOFWD:     /* check for forward request */
  596.           if(msgrcv(scmsgqid,&msg,1024,1L,IPC_NOWAIT|0600) > 0) {
  597.               switch(msg.mtext[0]){
  598.               case 'F': fwdflag = SPAWNBBS;  /* forwarding request */
  599.                     break;
  600.               case 'B': sendbeac();
  601.                     break;
  602.               default:  break;
  603.               }
  604.           }
  605.           break;
  606.         case SPAWNBBS:  spawnfwd();
  607.                         nsend = false;
  608.                         break;
  609.         case DOCONNECT: fwdcon();
  610.                         break;
  611.         case READXMIT : fwdsend();
  612.                         break;
  613.         case GETCON:    getcon();
  614.                         break;
  615.         case CLEARCON:  clearcon(nsend);
  616.                 if(!(nsend))    /* only do clearcon without N once*/
  617.                     nsend = true;
  618.                         break;
  619.         case WAITING:   break;
  620.         default: break;
  621.     }
  622.     if(fwdflag != NOFWD){ /*if forwarder, check for control*/
  623.         gotbytes = msgrcv(scmsgqid,&msg,256,(long)fwdstruct.pid,IPC_NOWAIT|0600);
  624.         switch(gotbytes){
  625.             case 0:     break;
  626.             case -1:    /*perror("axchk003");*/
  627.                         break;
  628.             default:    if(msg.mtext[0] == 'K'){
  629.                         kill(fwdstruct.pid,9);
  630.                         wait(NULLCHAR);
  631. #ifdef DEBUG
  632.             printf("clearing ques\n");
  633. #endif
  634.                         clearque(fwdstruct.pid);
  635.             fwdflag = NOFWD;
  636.             disc_ax25(fwdstruct.cbadr.axbbscb);
  637.                     fwdstruct.cbadr.axbbscb = NULLFWD;
  638.                         }
  639.                         else if(msg.mtext[0] == 'N'){
  640. #ifdef DEBUG
  641.                             printf("net:N received from BBS\n");
  642. #endif
  643.                             if(fwdbbsstate==YESCON){ /*if we are really connected*/
  644.                                 fwdbbsstate=WAIT;  /*wait until disconnect before next*/
  645.                                 disc_ax25(fwdstruct.cbadr.axbbscb); /*do the disconnect */
  646. #ifdef DEBUG
  647.                             printf("net:disconnect issued\n");
  648. #endif
  649.                             }
  650. #ifdef DEBUG
  651.                             printf("net:setting flag to CLEARCON\n");
  652. #endif
  653.                             fwdflag=CLEARCON;  /*set up for next connect*/
  654.                         }
  655.                         break;
  656.         } /*switch*/
  657.     } /* if forwarder active */
  658. }
  659.  
  660. spawnfwd()
  661. {
  662.     char arg1[20],arg2[20],arg3[20],arg4[20],arg5[20];
  663.  
  664.                   /*fork and exec the forwarder*/
  665.     if((fwdstruct.pid=fork()) == 0){              /* if this is the child*/
  666.         strcpy(arg1,"forward");
  667.         sprintf(arg2,"%d\0",rmsgqid);    /*tell the bbs what the message*/
  668.         sprintf(arg3,"%d\0",smsgqid);     /* que ids to use are*/
  669.         sprintf(arg4,"%d\0",rcmsgqid);
  670.         sprintf(arg5,"%d\0",scmsgqid);
  671.  
  672.             /*check for bad exec */
  673.         if(execlp(bbsexe,"xobbs",arg1,arg2,arg3,arg4,arg5,0) < 0){
  674.         fprintf(stderr,"Bad Exec on forwarder\n");
  675.         exit(1);
  676.     }
  677.     }/* if fwdstruct.pid is 0 */
  678.     else{
  679.         fwdflag=CLEARCON;  /*not the child, so set flag for next level*/
  680.     fwdstruct.gotbytes = 0;
  681.     fwdstruct.bytes = 0;
  682.     fwdstruct.proto = AX25;
  683.     fwdstruct.mtxtptr = fwdstruct.rmsgbuf.mtext;
  684.     }
  685. }
  686.     
  687. clearcon(nsend)
  688.     int nsend;
  689. {
  690.     int i;
  691.  
  692. #ifdef DEBUG
  693.     printf("net:clearcon:entering routine\n");
  694. #endif
  695.     for(i=0;i<10;i++)
  696.         conbuf[i][0]='\0';
  697. #ifdef DEBUG
  698.     printf("net:clearcon:Clearing ques\n");
  699. #endif
  700.     conindex=conchar=0;            /*clear the connect buffer*/
  701.     fwdflag=GETCON;
  702.     clearque(fwdstruct.pid);
  703.     if(nsend && fwdstruct.cbadr.axbbscb != NULLFWD){  /*don't send N to new bbs or no bbs */
  704.         msg.mtype = (long)fwdstruct.pid;
  705.     sprintf(msg.mtext,"N\0");
  706. #ifdef DEBUG
  707.         printf("net:Sending %s to bbs\n",msg.mtext);
  708. #endif
  709.         msgsnd(rcmsgqid,&msg,2,0600);
  710. #ifdef DEBUG
  711.         printf("net:clearcon:sent N to bbs process ID %d\n",fwdstruct.pid);
  712. #endif
  713.     }
  714. }
  715.     
  716.  
  717. getcon()                        /*routine called when fwdflag is "GETCON"*/
  718. {                               /* to read the connect request*/
  719.  
  720.     fwdstruct.gotbytes = msgrcv(smsgqid,&fwdstruct.rmsgbuf,256,(long)fwdstruct.pid,IPC_NOWAIT|0600);  /* is there anything in the pipe?*/
  721.     switch(fwdstruct.gotbytes){
  722.         case 0:     return;
  723.         case -1:    /*perror("getcon001");*/
  724.                     break;
  725.         default:    strncpy(conbuf[conindex],fwdstruct.rmsgbuf.mtext,fwdstruct.gotbytes);
  726.             if(fwdstruct.rmsgbuf.mtext[0] != 0x04){
  727.                         conbuf[conindex++][fwdstruct.gotbytes] = '\0';
  728.                         break;
  729.                    }
  730.                    else
  731.                    fwdflag = DOCONNECT;
  732.     }
  733.     fwdstruct.gotbytes=0;
  734. }
  735.  
  736. fwdcon()
  737. {
  738.     char *argv[10];
  739.  
  740.     char buf[128];
  741.     static char temp[] = "con";
  742.  
  743.     int numdigis;
  744.     int i;
  745.       
  746.     argv[1] = &conbuf[0][0];    /* get device to use*/
  747.     argv[2] = &conbuf[1][0];    /* get who to connect to*/
  748.     numdigis=atoi(&conbuf[2][0]);
  749.     for(i=0; i < numdigis;i++)
  750.         argv[3+i] = &conbuf[3+i][0];
  751.  
  752.     argv[0]= temp;              /* set up for the doconfwd() call */
  753.  
  754.     fflush(stdout);
  755.      if(!doconfwd(3+numdigis,argv)){               /*do the connect*/
  756.          sprintf(msg.mtext,"OK\n");
  757.          msg.mtype = (long)fwdstruct.pid;
  758.          if(msgsnd(rmsgqid,&msg,3,0600) < 0)
  759.              perror("fwdcon001");
  760.      fwdflag=WAITING;
  761.          return 0;
  762.      }
  763.      else{
  764.          sprintf(buf,"NOGOOD\n");
  765.      msg.mtype = (long)fwdstruct.pid;
  766.          if(msgsnd(rmsgqid,&msg,7,0600) < 0)
  767.              perror("fwdcon002");
  768.          fwdflag=CLEARCON;
  769.          return 1;
  770.     }
  771. }
  772.  
  773. void
  774. fwdstate(axp,old,new)        /*w2xo      10-24-88 */
  775. struct ax25_cb *axp;
  776. int old,new;
  777. {
  778.  
  779.  
  780.     switch(new){
  781.     case DISCONNECTED:  if(fwdflag==READXMIT){
  782.                 fwdflag=CLEARCON;
  783.                 }
  784.                 fwdbbsstate=NOCON;
  785.                 kill(fwdstruct.pid,SIGUSR1); /*tell bbs about discon*/
  786.                 break;
  787.                             
  788.     case CONNECTED:        fwdflag=READXMIT;
  789.                 fwdstruct.bytes = 32; /*jump start t_upcall*/
  790.                 fwdbbsstate=YESCON;
  791.                 break;
  792.         default:            break;
  793.     }
  794. }
  795.  
  796. void
  797. fwdxmit(axp,cnt)
  798. struct ax25_cb *axp;
  799. int16 cnt;
  800. {
  801.         /*all we want to do here is establish the max number of*/
  802.         /* bytes to send at any one time*/
  803.  
  804.     if(axp == fwdstruct.cbadr.axbbscb)
  805.         fwdstruct.bytes = cnt;
  806. }
  807.  
  808. void
  809. fwdrecv(axp,cnt)        /*w2xo  10-24-88  */
  810. struct ax25_cb *axp;        /* send chars down pipe to forwarding bbs */
  811. int16 cnt;
  812. {
  813.     struct mbuf *bp;
  814.     struct mbuf *recv_ax25();
  815.     
  816.     if((bp = recv_ax25(axp,cnt)) == NULLBUF)  /*nothing there*/
  817.         return;
  818.  
  819.     while(bp != NULLBUF){
  820.         strncpy(msg.mtext,bp->data,bp->cnt);
  821.     msg.mtype = (long)fwdstruct.pid;
  822.         if(msgsnd(rmsgqid,&msg,bp->cnt,0600) < 0)
  823.             perror("fwdrecv");
  824.         bp=free_mbuf(bp);
  825.     }
  826. }
  827.  
  828. fwdsend()        /* service bbs ax25 connections w2xo 10-24-88*/
  829. {
  830.     int size,testsize;
  831.     struct mbuf *bp;
  832.     char *cp;
  833.  
  834.     if(fwdstruct.cbadr.axbbscb != NULLFWD){
  835.         if(fwdstruct.gotbytes < 1)
  836.             if((fwdstruct.gotbytes=msgrcv(smsgqid,&fwdstruct.rmsgbuf,256,(long)fwdstruct.pid,
  837.                IPC_NOWAIT|0600)) < 1)
  838.                  return;   /*return if nothing to send*/
  839.             else
  840.                 fwdstruct.mtxtptr = fwdstruct.rmsgbuf.mtext; /*new message buffer, set to start*/
  841.  
  842.         testsize = min(fwdstruct.bytes,fwdstruct.cbadr.axbbscb->paclen+1);      /* get the minimum of the # */
  843.         size = min(testsize, fwdstruct.gotbytes) +1;       /* of bytes avail and paclen*/
  844.         bp = alloc_mbuf((int16)size);                  /* then min of avail and have*/
  845.         cp = bp->data;
  846.         *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  847.         bp->cnt = 1;
  848.         while(bp->cnt < size){
  849.             *cp++ = *fwdstruct.mtxtptr++;
  850.             bp->cnt++;
  851.             fwdstruct.gotbytes--;
  852.         }
  853.         send_ax25(fwdstruct.cbadr.axbbscb,bp);
  854.     } /*if active */
  855. }
  856.  
  857. /* Initiate AX.25 forwarding connection to remote bbs */
  858. doconfwd(argc,argv)
  859. int argc;
  860. char **argv;
  861.  {
  862.     void fwdrecv(),fwdxmit(),fwdstate();
  863.     struct ax25_addr dest;
  864.     struct ax25 addr;
  865.     struct ax25_cb *open_ax25();
  866.     struct interface *ifp;
  867.     struct mboxsess *mbp;
  868.     extern int16 axwindow;
  869.     int i;
  870.  
  871.     for(ifp = ifaces; ifp != NULLIF; ifp = ifp->next)
  872.         if(strcmp(argv[1],ifp->name) == 0)
  873.             break;
  874.     if(ifp == NULLIF){
  875.         printf("Interface %s unknown\n",argv[1]);
  876.         return 1;
  877.     }
  878.  
  879.     mbp = base;            /* point to the session base */
  880.     while (mbp != NULLMBS) {    /* and climb the session */
  881.         if (!strncmp(mbp->call,argv[2],strlen(mbp->call)))
  882.             return 1;
  883.         mbp = mbp->next;    /* bomb out if session to this bbs */
  884.     }                /* exists */
  885.  
  886.     setcall(&dest,argv[2]);
  887. #ifndef NETROM
  888.     ASSIGN(addr.source,mycall);
  889. #else
  890.     memcpy(&addr.source,ifp->hwaddr,AXALEN);
  891. #endif
  892.     setcall(&addr.dest,argv[2]);
  893.     for(i=3; i < argc; i++)
  894.         setcall(&addr.digis[i-3],argv[i]);
  895.  
  896.     addr.ndigis = i - 3;
  897.     fwdstruct.cbadr.axbbscb = open_ax25(&addr,axwindow,fwdrecv,fwdxmit,fwdstate,ifp,(char *)0);
  898.     return 0;
  899. }
  900.  
  901.  
  902. fgetline(fd,s)
  903.     int fd;
  904.     char *s;
  905. {
  906.     int i;
  907.     char c;
  908.     i=0;
  909.     while((c=xogetc(fd)) && ((c != '\n') && (c != '\r')))
  910.         s[i++] = c;
  911.  
  912.     s[i] = '\0';
  913.     return(i);
  914. }
  915.  
  916.  
  917. char xogetc(fd)
  918. {
  919.     char c;
  920.     if(read(fd,&c,1)){
  921.         c &= (char)0x7f;        /*strip 8th bit and up*/
  922.         if(c=='\r')
  923.             c='\n';
  924.         return(c);
  925.     }
  926.     else return('\0');
  927. }
  928.  
  929.  
  930. void
  931. axinit()
  932. {
  933.     int fd;
  934.  
  935.     if((smsgqid=msgget(SENDKEY,IPC_CREAT|0600)) < 0){
  936.         perror("msgget smsgqid:");
  937.         exit(1);
  938.     }
  939.     else
  940.         printf("Send message que identifier is:%d\n",smsgqid);
  941.         
  942.     if((rmsgqid=msgget(RCVKEY,IPC_CREAT|0600)) < 0){
  943.         perror("msgget rmsgqid:");
  944.         exit(1);
  945.     }
  946.     else
  947.         printf("Receive message que identifier is:%d\n",rmsgqid);
  948.  
  949.     if((scmsgqid=msgget(SCTLKEY,IPC_CREAT|0600)) < 0){
  950.         perror("msgget scmsgqid:");
  951.         exit(1);
  952.     }
  953.     else {
  954.         printf("Control send message que identifier is:%d\n",scmsgqid);
  955.     }
  956.  
  957.     if((rcmsgqid=msgget(RCTLKEY,IPC_CREAT|0600)) < 0){
  958.         perror("msgget rcmsgqid:");
  959.         exit(1);
  960.     }
  961.     else
  962.         printf("Control receive message que identifier is:%d\n",rcmsgqid);
  963.  
  964. }
  965.  
  966. clearque(pid)
  967.     int pid;
  968. {
  969.     while(msgrcv(smsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  970.         ;
  971.     while(msgrcv(rmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  972.         ;
  973.     while(msgrcv(scmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  974.         ;
  975.     while(msgrcv(rcmsgqid,&msg,256,(long)pid,IPC_NOWAIT|0600) > 0)
  976.         ;
  977. }
  978.  
  979. calleq(axp,addr)
  980.     struct ax25_cb *axp;
  981.     struct ax25_addr *addr;
  982. {
  983.     register int i;
  984.  
  985.     if(memcmp(axp->addr.source.call,addr->call,ALEN) != 0)
  986.         return 0;
  987.     if((axp->addr.source.ssid & SSID) != (addr->ssid & SSID))
  988.         return 0;
  989.     return 1;
  990. }
  991.  
  992. sendbeac()
  993. {
  994.     int gotbytes;
  995.     struct mbuf *bp;
  996.     char *cp,*kp;
  997.     struct interface *iface;
  998.         extern struct interface *ifaces;
  999.                 
  1000.     if((gotbytes = msgrcv(smsgqid,&msg,1024,(long)2,0600)) < 0){
  1001.         perror("sendbeac:receiving message");
  1002.         return;
  1003.     }
  1004.     
  1005.     for(iface = ifaces; iface->next != NULLIF ; iface = iface->next){
  1006.         if((iface->name[0] != 'a') || (iface->name[1] != 'x'))
  1007.             continue;
  1008.             bp = alloc_mbuf((int16)(gotbytes + 2));                  /* then min of avail and have*/
  1009.             cp = bp->data;
  1010.             kp = msg.mtext;
  1011.             *cp++ = PID_FIRST | PID_LAST | PID_NO_L3;
  1012.             bp->cnt = 1;
  1013.             do{
  1014.                 *cp++ = *kp++;
  1015.                 bp->cnt++;
  1016.             }while(bp->cnt < (gotbytes + 1));
  1017.  
  1018. #ifdef SID2
  1019.         ax_output(iface,(char*)&ax25_bdcst,(char *)&bbscall,(PID_FIRST |PID_LAST|PID_NO_L3),bp);
  1020. #else
  1021.         ax_output(iface,(char*)&ax25_bdcst,(char *)mycall,(PID_FIRST |PID_LAST|PID_NO_L3),bp);
  1022. #endif
  1023.  
  1024.         }
  1025. }
  1026.  
  1027.  
  1028. #else /* not XOBBS */
  1029.  
  1030. #include <stdio.h>
  1031. #include <time.h>
  1032. #include <ctype.h>
  1033. #ifdef    UNIX
  1034. #ifdef    UNIX
  1035. #undef    toupper
  1036. #undef    tolower
  1037. #endif
  1038. #include <sys/types.h>
  1039. #endif
  1040. #include "global.h"
  1041. #include "mbuf.h"
  1042. #include "ax25.h"
  1043. #include "timer.h"
  1044. #include "iface.h"
  1045. #include "lapb.h"
  1046. #include "netrom.h"
  1047. #include "nr4.h"
  1048. #include "ax_mbx.h"
  1049. #include "cmdparse.h"
  1050. #ifdef    UNIX
  1051. #include <memory.h>
  1052. #include <string.h>
  1053. #endif
  1054.  
  1055. #ifdef    BSD
  1056. char *sprintf();
  1057. #endif
  1058.  
  1059. /*
  1060. #define MBDEBUG
  1061. */
  1062.  
  1063. struct mbx *mbox[NUMMBX] ;
  1064. int ax25mbox ;
  1065.  
  1066. static char mbbanner[] =
  1067.     "[NET-$]\rWelcome to the %s TCP/IP Mailbox\r(C)hat, (S)end, (B)ye >\r" ;
  1068. static char mbmenu[] = "(C)hat, (S)end, (B)ye >\r" ;
  1069.  
  1070. dombox(argc, argv)
  1071. int argc ;
  1072. char *argv[] ;
  1073. {
  1074.     if (argc < 2) {
  1075.         domboxdisplay() ;
  1076.         return 0 ;
  1077.     }
  1078.  
  1079.     if (argv[1][0] == 'y' || (strcmp(argv[1],"on") == 0))
  1080.         ax25mbox = 1 ;
  1081.     else if (argv[1][0] == 'n' || (strcmp(argv[1],"off") == 0))
  1082.         ax25mbox = 0 ;
  1083.     else if (argv[1][0] == '?')
  1084.         printf("ax25 mailbox is %s\n", ax25mbox ? "on" : "off") ;
  1085.     else
  1086.         printf("usage: mbox [y|n|?]\n") ;
  1087.  
  1088.     return 0 ;
  1089. }
  1090.  
  1091. static domboxdisplay()
  1092. {
  1093.     int i ;
  1094.     struct mbx *m ;
  1095.     static char *states[] = {"NONE","CMD","SUBJ","DATA"} ;
  1096.     static char *mbtype[] = {"NONE","AX25 ","NET/ROM"} ;
  1097.     
  1098.     printf(" User     State    Type    &cb\n") ;
  1099.  
  1100.     for (i = 0 ; i < NUMMBX ; i++)
  1101.         if ((m = mbox[i]) != NULLMBX)
  1102.             printf("%10s %4s  %7s   %04x\n", m->name, states[m->state],
  1103.                     mbtype[m->type],
  1104.                     m->type == MBX_AX25 ? (int)m->cb.ax25_cb : (int)m->cb.nr4_cb) ;
  1105. }
  1106.  
  1107.     
  1108. static struct mbx *
  1109. newmbx()
  1110. {
  1111.     int i ;
  1112.     struct mbx *m ;
  1113.  
  1114.     for (i = 0 ; i < NUMMBX ; i++)
  1115.         if (mbox[i] == NULLMBX) {
  1116.             if ((m = mbox[i] = (struct mbx *)calloc(1,sizeof(struct mbx)))
  1117.                 == NULLMBX)
  1118.                 return NULLMBX ;
  1119.             m->mbnum = i ;
  1120.             return m ;
  1121.         }
  1122.  
  1123.     /* If we get here, there are no free mailbox sessions */
  1124.  
  1125.     return NULLMBX ;
  1126. }
  1127.  
  1128.  
  1129. /* Incoming mailbox session via ax.25 */
  1130.  
  1131. void
  1132. mbx_incom(axp,cnt)
  1133. register struct ax25_cb *axp ;
  1134. int16 cnt ;
  1135. {
  1136.     struct mbx *m ;
  1137.     struct mbuf *bp, *recv_ax25() ;
  1138.     char *cp ;
  1139.     extern char hostname[] ;
  1140.     void mbx_rx(), mbx_state() ;
  1141.     extern char *index() ;
  1142.     
  1143.     if ((m = newmbx()) == NULLMBX) {
  1144.         disc_ax25(axp) ;    /* no memory! */
  1145.         return ;
  1146.     }
  1147.  
  1148.     m->state = MBX_CMD ;    /* start in command state */
  1149.     m->type = MBX_AX25 ;    /* this is an ax.25 mailbox session */
  1150.     m->cb.ax25_cb = axp ;
  1151.  
  1152.     pax25(m->name,&axp->addr.dest) ;
  1153.     cp = index(m->name,'-') ;
  1154.     if (cp != NULLCHAR)            /* get rid of SSID */
  1155.         *cp = '\0' ;
  1156.  
  1157.     m->lp = m->line ;        /* point line pointer at buffer */
  1158.     axp->r_upcall = mbx_rx ;
  1159.     axp->s_upcall = mbx_state ;
  1160.     axp->user = (char *)m ;
  1161.  
  1162.     /* The following is necessary because we didn't know we had a */
  1163.     /* "real" ax25 connection until a data packet came in.  We    */
  1164.     /* can't be spitting banners out at every station who connects, */
  1165.     /* since they might be a net/rom or IP station.  Sorry.  */
  1166.     
  1167.     bp = recv_ax25(axp,cnt) ;        /* get the initial input */
  1168.     free_p(bp) ;                    /* and throw it away to avoid confusion */
  1169.  
  1170.     /* Now say hi */
  1171.     
  1172.     if ((bp = alloc_mbuf((int16)(strlen(hostname) + strlen(mbbanner) + 2))) == NULLBUF) {
  1173.         disc_ax25(axp) ; /* mbx_state will fix stuff up */
  1174.         return ;
  1175.     }
  1176.  
  1177.     *bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;    /* pid */
  1178.     (void)sprintf(bp->data+1,mbbanner,hostname) ;
  1179.     bp->cnt = strlen(bp->data+1) + 1 ;
  1180.  
  1181.     send_ax25(axp,bp) ;                    /* send greeting message and menu */
  1182. }
  1183.  
  1184. /* receive upcall for ax.25 */
  1185. /* mbx_rx collects lines, and calls mbx_line when they are complete. */
  1186. /* If the lines get too long, it arbitrarily breaks them. */
  1187.  
  1188. void mbx_rx(axp,cnt)
  1189. struct ax25_cb *axp ;
  1190. int16 cnt ;
  1191. {
  1192.     struct mbuf *bp, *recv_ax25() ;
  1193.     struct mbx *m ;
  1194.     char c ;
  1195.     int mbx_line() ;
  1196.     
  1197.     m = (struct mbx *)axp->user ;
  1198.     
  1199.     if ((bp = recv_ax25(axp,cnt)) == NULLBUF)
  1200.         return ;
  1201.  
  1202.     while (pullup(&bp,&c,1) == 1) {
  1203.         if (c == '\r') {
  1204.             *m->lp = '\0' ;            /* null terminate */
  1205.             if (mbx_line(m) == -1) {    /* call the line processor */
  1206.                 free_p(bp) ;        /* toss the rest */
  1207.                 break ;                /* get out - we're obsolete */
  1208.             }
  1209.             m->lp = m->line ;        /* reset the pointer */
  1210.         }
  1211.         else if ((m->lp - m->line) == (MBXLINE - 1)) {
  1212.             *m->lp++ = c ;
  1213.             *m->lp = '\0' ;
  1214.             if (mbx_line(m) == -1) {
  1215.                 free_p(bp) ;
  1216.                 break ;
  1217.             }
  1218.             m->lp = m->line ;
  1219.         }
  1220.         else
  1221.             *m->lp++ = c ;
  1222.     }
  1223. }
  1224.  
  1225. /* state upcall for ax.25 */
  1226.  
  1227. /*ARGSUSED*/
  1228. void mbx_state(axp,old,new)
  1229. struct ax25_cb *axp ;
  1230. int old, new ;
  1231. {
  1232.     struct mbx *m ;
  1233.     void free_mbx() ;
  1234.     
  1235.     m = (struct mbx *)axp->user ;
  1236.  
  1237.     /* dummy for now ... */
  1238.     if (new == DISCONNECTED) {
  1239.         axp->user = NULLCHAR ;
  1240.         free_mbx(m) ;
  1241.     }
  1242. }
  1243.  
  1244.  
  1245. /* Incoming mailbox session via net/rom */
  1246.  
  1247. void
  1248. mbx_nr4incom(cb)
  1249. register struct nr4cb *cb ;
  1250. {
  1251.     struct mbx *m ;
  1252.     struct mbuf *bp ;
  1253.     char *cp ;
  1254.     extern char hostname[] ;
  1255.     void mbx_nr4rx(), mbx_nr4state() ;
  1256.     extern char *index() ;
  1257.     
  1258.     if ((m = newmbx()) == NULLMBX) {
  1259.         disc_nr4(cb) ;    /* no memory! */
  1260.         return ;
  1261.     }
  1262.  
  1263.     m->state = MBX_CMD ;    /* start in command state */
  1264.     m->type = MBX_NETROM ;    /* mailbox session type is net/rom */
  1265.     m->cb.nr4_cb = cb ;
  1266.  
  1267.     pax25(m->name,&cb->user) ;
  1268.     cp = index(m->name,'-') ;
  1269.     if (cp != NULLCHAR)            /* get rid of SSID */
  1270.         *cp = '\0' ;
  1271.  
  1272.     m->lp = m->line ;        /* point line pointer at buffer */
  1273.     cb->r_upcall = mbx_nr4rx ;
  1274.     cb->s_upcall = mbx_nr4state ;
  1275.     cb->puser = (char *)m ;
  1276.  
  1277.     /* Say hi */
  1278.     
  1279.     if ((bp = alloc_mbuf((int16)(strlen(hostname) + strlen(mbbanner) + 1))) == NULLBUF) {
  1280.         disc_nr4(cb) ; /* mbx_nr4state will fix stuff up */
  1281.         return ;
  1282.     }
  1283.  
  1284.     (void)sprintf(bp->data,mbbanner,hostname) ;
  1285.     bp->cnt = strlen(bp->data) ;
  1286.  
  1287.     send_nr4(cb,bp) ;                    /* send greeting message and menu */
  1288. }
  1289.  
  1290. /* receive upcall for net/rom */
  1291. /* mbx_nr4rx collects lines, and calls mbx_line when they are complete. */
  1292. /* If the lines get too long, it arbitrarily breaks them. */
  1293.  
  1294. void mbx_nr4rx(cb,cnt)
  1295. struct nr4cb *cb ;
  1296. int16 cnt ;
  1297. {
  1298.     struct mbuf *bp ;
  1299.     struct mbx *m ;
  1300.     char c ;
  1301.     int mbx_line() ;
  1302.     
  1303.     m = (struct mbx *)cb->puser ;
  1304.     
  1305.     if ((bp = recv_nr4(cb,cnt)) == NULLBUF)
  1306.         return ;
  1307.  
  1308.     while (pullup(&bp,&c,1) == 1) {
  1309.         if (c == '\r') {
  1310.             *m->lp = '\0' ;            /* null terminate */
  1311.             if (mbx_line(m) == -1) {    /* call the line processor */
  1312.                 free_p(bp) ;        /* toss the rest */
  1313.                 break ;                /* get out - we're obsolete */
  1314.             }
  1315.             m->lp = m->line ;        /* reset the pointer */
  1316.         }
  1317.         else if ((m->lp - m->line) == (MBXLINE - 1)) {
  1318.             *m->lp++ = c ;
  1319.             *m->lp = '\0' ;
  1320.             if (mbx_line(m) == -1) {
  1321.                 free_p(bp) ;
  1322.                 break ;
  1323.             }
  1324.             m->lp = m->line ;
  1325.         }
  1326.         else
  1327.             *m->lp++ = c ;
  1328.     }
  1329. }
  1330.  
  1331. /* state upcall for net/rom */
  1332.  
  1333. /*ARGSUSED*/
  1334. void mbx_nr4state(cb,old,new)
  1335. struct nr4cb *cb ;
  1336. int old, new ;
  1337. {
  1338.     struct mbx *m ;
  1339.     void free_mbx() ;
  1340.     
  1341.     m = (struct mbx *)cb->puser ;
  1342.  
  1343.     if (new == NR4STDISC) {
  1344.         cb->puser = NULLCHAR ;
  1345.         free_mbx(m) ;
  1346.     }
  1347. }
  1348.  
  1349. static void
  1350. free_mbx(m)
  1351. struct mbx *m ;
  1352. {
  1353.     if (m->to != NULLCHAR)
  1354.         free(m->to) ;
  1355.  
  1356.  
  1357.     if (m->tofrom != NULLCHAR)
  1358.         free(m->tofrom) ;
  1359.  
  1360.     if (m->tomsgid != NULLCHAR)
  1361.         free(m->tomsgid) ;
  1362.         
  1363.     if (m->tfile != NULLFILE)
  1364.         fclose(m->tfile) ;
  1365.  
  1366.     mbox[m->mbnum] = NULLMBX ;
  1367.     
  1368.     free(m) ;
  1369. }
  1370.  
  1371.  
  1372. static 
  1373. mbx_line(m)
  1374. struct mbx *m ;
  1375. {
  1376.     void ax_session(), nr4_session(), mbx_disc() ;
  1377.     char *host ;
  1378.     extern char hostname[] ;
  1379.     char fullfrom[80] ;
  1380.     
  1381.     if (m->state == MBX_CMD) {
  1382.         switch (tolower(m->line[0])) {
  1383.             case 'b':    /* bye - bye */
  1384.                 mbx_disc(m) ;
  1385.                 return -1 ;    /* tell line processor to quit */
  1386.                 break ;
  1387.             case 'c':    /* chat */
  1388.                 switch (m->type) {
  1389.                   case MBX_AX25:
  1390.                     m->cb.ax25_cb->user = NULLCHAR ;
  1391.                     ax_session(m->cb.ax25_cb,0) ;    /* make it a chat session */
  1392.                     break ;
  1393.                   case MBX_NETROM:
  1394.                     m->cb.nr4_cb->puser = NULLCHAR ;
  1395.                     nr4_session(m->cb.nr4_cb) ;
  1396.                     break ;
  1397.                 }
  1398.                 free_mbx(m) ;
  1399.                 return -1 ;
  1400.                 break ;
  1401.             case 's': {
  1402.                 int badsubj = 0 ;
  1403.  
  1404.                 /* Get S-command type (B,P,T, etc.) */
  1405.                 
  1406.                 if (m->line[1] == '\0')
  1407.                     m->stype = ' ' ;
  1408.                 else
  1409.                     m->stype = toupper(m->line[1]) ;
  1410.                     
  1411.                 if (mbx_to(m) == -1) {
  1412.                     if (m->sid & MBX_SID)
  1413.                         mbx_msg(m,"NO\r") ;
  1414.                     else {
  1415.                         mbx_msg(m,
  1416.                             "S command syntax error - format is:\r") ;
  1417.                         mbx_msg(m,
  1418.                           "  S name [@ host] [< from_addr] [$bulletin_id]\r") ;
  1419.                     }
  1420.                     badsubj++ ;
  1421.                 }
  1422.                 else if (validate_address(m->to) == 0)     {
  1423.                     if (m->sid & MBX_SID)
  1424.                         mbx_msg(m, "NO\r") ;
  1425.                     else
  1426.                         mbx_msg(m, "Bad user or host name\r") ;
  1427.                     free(m->to) ;
  1428.                     m->to = NULLCHAR ;
  1429.                     if (m->tofrom) {
  1430.                         free(m->tofrom) ;
  1431.                         m->tofrom = NULLCHAR ;
  1432.                     }
  1433.                     if (m->tomsgid) {
  1434.                         free(m->tomsgid) ;
  1435.                         m->tomsgid = NULLCHAR ;
  1436.                     }
  1437.                     badsubj++ ;
  1438.                 }
  1439.  
  1440.                 if (badsubj)
  1441.                     mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1442.                 else {
  1443.                     m->state = MBX_SUBJ ;
  1444.                     mbx_msg(m,    (m->sid & MBX_SID) ? "OK\r" : "Subject:\r") ;
  1445.                 }
  1446.                 break ;
  1447.             }
  1448.             case '[':    /* This is a BBS - say "OK", not "Subject:" */
  1449.               {
  1450.                 int len = strlen(m->line) ;
  1451.                 
  1452.                 if (m->line[len - 1] == ']') { /* must be an SID */
  1453.                     m->sid = MBX_SID ;
  1454.                     /* Now check to see if this is an RLI board. */
  1455.                     /* As usual, Hank does it a bit differently from */
  1456.                     /* the rest of the world. */
  1457.                     if (len >= 5)        /* [RLI] at a minimum */
  1458.                         if (strncmp(&m->line[1],"RLI",3) == 0)
  1459.                             m->sid |= MBX_SID_RLI ;
  1460.                     
  1461.                     mbx_msg(m,">\r") ;
  1462.                 }
  1463.               }
  1464.               break ;
  1465.             case 'f':
  1466.                 if (m->line[1] == '>' && (m->sid & MBX_SID)) {
  1467.                     /* RLI BBS' expect us to disconnect if we */
  1468.                     /* have no mail for them, which of course */
  1469.                     /* we don't, being rather haughty about our */
  1470.                     /* protocol superiority. */
  1471.                     if (m->sid & MBX_SID_RLI) {
  1472.                         mbx_disc(m) ;
  1473.                         return -1 ;
  1474.                     } else
  1475.                         mbx_msg(m,">\r") ;
  1476.                     break ;
  1477.                 }
  1478.                 /* Otherwise drop through to "huh?" */
  1479.             default:
  1480.                 mbx_msg(m,"Huh?\r") ;
  1481.                 mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1482.         }
  1483.     return 0 ;
  1484.     }
  1485.     else if (m->state == MBX_SUBJ) {
  1486.         if (mbx_data(m) == -1) {
  1487.             mbx_msg(m,"Can't create temp file for mail\r") ;
  1488.             mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1489.             free(m->to) ;
  1490.             m->to = NULLCHAR ;
  1491.             if (m->tofrom) {
  1492.                 free(m->tofrom) ;
  1493.                 m->tofrom = NULLCHAR ;
  1494.             }
  1495.             if (m->tomsgid) {
  1496.                 free(m->tomsgid) ;
  1497.                 m->tomsgid = NULLCHAR ;
  1498.             }
  1499.             m->state = MBX_CMD ;
  1500.             return 0 ;
  1501.         }
  1502.         m->state = MBX_DATA ;
  1503.         if ((m->sid & MBX_SID) == 0)
  1504.             mbx_msg(m,
  1505.               "Enter message.  Terminate with /EX or ^Z in first column:\r") ;
  1506.         return 0 ;
  1507.     }
  1508.     else if (m->state == MBX_DATA) {
  1509.         if (m->line[0] == 0x1a ||
  1510.             strcmp(m->line, "/ex") == 0 ||
  1511.             strcmp(m->line, "/EX") == 0) {
  1512.             if ((host = index(m->to,'@')) == NULLCHAR)
  1513.                 host = hostname ;        /* use our hostname */
  1514.             else
  1515.                 host++ ;                /* use the host part of address */
  1516.  
  1517.             /* make up full from name for work file */
  1518.             (void)sprintf(fullfrom,"%s@%s",m->name,hostname) ;
  1519.             
  1520.             fseek(m->tfile,0L,0) ;        /* reset to beginning */
  1521.             if (queuejob((struct tcb *)0,m->tfile,host,m->to,fullfrom) != 0)
  1522.                 mbx_msg(m,
  1523.                         "Couldn't queue message for delivery\r") ;
  1524.  
  1525.             free(m->to) ;
  1526.             m->to = NULLCHAR ;
  1527.             if (m->tofrom) {
  1528.                 free(m->tofrom) ;
  1529.                 m->tofrom = NULLCHAR ;
  1530.             }
  1531.             if (m->tomsgid) {
  1532.                 free(m->tomsgid) ;
  1533.                 m->tomsgid = NULLCHAR ;
  1534.             }
  1535.             fclose(m->tfile) ;
  1536.             m->tfile = NULLFILE ;
  1537.             m->state = MBX_CMD ;
  1538.             mbx_msg(m, (m->sid & MBX_SID) ? ">\r" : mbmenu) ;
  1539.             return 0 ;
  1540.         }
  1541.         /* not done yet! */
  1542.         fprintf(m->tfile,"%s\n",m->line) ;
  1543.         return 0 ;
  1544.     }
  1545.     return 0 ;
  1546. }
  1547.  
  1548. static
  1549. mbx_msg(m,msg)
  1550. struct mbx *m ;
  1551. char msg[] ;
  1552. {
  1553.     int len ;
  1554.     struct mbuf *bp ;
  1555.     struct ax25_cb *axp ;
  1556.     struct nr4cb *cb ;
  1557.  
  1558.     len = strlen(msg) ;
  1559.  
  1560.     switch (m->type) {
  1561.       case MBX_AX25:
  1562.         axp = m->cb.ax25_cb ;
  1563.             
  1564.         if ((bp = alloc_mbuf((int16)(len+1))) == NULLBUF) {
  1565.             disc_ax25(axp) ;
  1566.             return -1 ;
  1567.         }
  1568.  
  1569.         bp->cnt = len + 1 ;
  1570.     
  1571.         *bp->data = PID_FIRST | PID_LAST | PID_NO_L3 ;
  1572.     
  1573.         memcpy(bp->data+1, msg, len) ;
  1574.  
  1575.         send_ax25(axp,bp) ;
  1576.  
  1577.         break ;
  1578.  
  1579.       case MBX_NETROM:
  1580.         cb = m->cb.nr4_cb ;
  1581.  
  1582.         if ((bp = alloc_mbuf((int16)len)) == NULLBUF) {
  1583.             disc_nr4(cb) ;
  1584.             return -1 ;
  1585.         }
  1586.  
  1587.         bp->cnt = len ;
  1588.  
  1589.         memcpy(bp->data, msg, len) ;
  1590.  
  1591.         send_nr4(cb, bp) ;
  1592.  
  1593.         break ;
  1594.     }
  1595.     return 0 ;
  1596. }
  1597.  
  1598.  
  1599. /* States for send line parser state machine */
  1600.  
  1601. #define        SKIP_CMD        1
  1602. #define        LOOK_FOR_USER    2
  1603. #define        IN_USER            3
  1604. #define        AFTER_USER        4
  1605. #define        LOOK_FOR_HOST    5
  1606. #define        IN_HOST            6
  1607. #define        AFTER_HOST        7
  1608. #define        LOOK_FOR_FROM    8
  1609. #define        IN_FROM            9
  1610. #define        AFTER_FROM        10
  1611. #define        LOOK_FOR_MSGID    11
  1612. #define        IN_MSGID        12
  1613. #define        FINAL_STATE        13
  1614. #define        ERROR_STATE        14
  1615.  
  1616. /* Prepare the addressee.  If the address is bad, return -1, otherwise
  1617.  * return 0
  1618.  */
  1619. static
  1620. mbx_to(m)
  1621. struct mbx *m ;
  1622. {
  1623.     register char *cp ;
  1624.     int state ;
  1625.     char *user, *host, *from, *msgid ;
  1626.     int userlen = 0, hostlen = 0, fromlen = 0, msgidlen = 0 ;
  1627.     
  1628.     cp = m->line ;
  1629.  
  1630.     for (state = SKIP_CMD ; state < FINAL_STATE ; cp++) {
  1631. #ifdef MBDEBUG
  1632.         printf("State is %d, char is %c\n", state, *cp) ;
  1633. #endif
  1634.         switch (state) {
  1635.             case SKIP_CMD:
  1636.                 if (*cp == '\0')
  1637.                     state = ERROR_STATE ;        /* no user */
  1638.                 else if (isspace(*cp))
  1639.                     state = LOOK_FOR_USER ;
  1640.                 break ;
  1641.             case LOOK_FOR_USER:
  1642.                 if (*cp == '\0' || *cp == '@' || *cp == '<' || *cp == '$')
  1643.                     state = ERROR_STATE ;        /* no user */
  1644.                 else if (!isspace(*cp)) {        /* found start of user */
  1645.                     user = cp ;                    /* point at start */
  1646.                     userlen++ ;                    /* start counting */
  1647.                     state = IN_USER ;
  1648.                 }
  1649.                 break ;
  1650.             case IN_USER:
  1651.                 switch (*cp) {
  1652.                     case '\0':                    /* found username only */
  1653.                         state = FINAL_STATE ;
  1654.                         break ;
  1655.                     case '@':
  1656.                         state = LOOK_FOR_HOST ;    /* hostname should follow */
  1657.                         break ;
  1658.                     case '<':
  1659.                         state = LOOK_FOR_FROM ;    /* from name should follow */
  1660.                         break ;
  1661.                     case '$':
  1662.                         state = LOOK_FOR_MSGID ; /* message id should follow */
  1663.                         break ;
  1664.                     default:
  1665.                         if (isspace(*cp))
  1666.                             state = AFTER_USER ;    /* white space */
  1667.                         else
  1668.                             userlen++ ;                /* part of username */
  1669.                 }
  1670.                 break ;
  1671.             case AFTER_USER:
  1672.                 switch (*cp) {
  1673.                     case '\0':
  1674.                         state = FINAL_STATE ;        /* found username only */
  1675.                         break ;
  1676.                     case '@':
  1677.                         state = LOOK_FOR_HOST ;        /* hostname follows */
  1678.                         break ;
  1679.                     case '<':
  1680.                         state = LOOK_FOR_FROM ;        /* fromname follows */
  1681.                         break ;
  1682.                     case '$':
  1683.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1684.                         break ;
  1685.                     default:
  1686.                         if (!isspace(*cp))
  1687.                             state = ERROR_STATE ;
  1688.                 }
  1689.                 break ;
  1690.             case LOOK_FOR_HOST:
  1691.                 switch (*cp) {
  1692.                     case '\0':                    /* user@? */
  1693.                     case '@':                    /* user@@ */
  1694.                     case '<':                    /* user@< */
  1695.                     case '$':                    /* user@$ */
  1696.                         state = ERROR_STATE ;
  1697.                         break ;
  1698.                     default:
  1699.                         if (!isspace(*cp)) {
  1700.                             host = cp ;
  1701.                             hostlen++ ;
  1702.                             state = IN_HOST ;
  1703.                         }
  1704.                 }
  1705.                 break ;
  1706.             case IN_HOST:
  1707.                 switch (*cp) {
  1708.                     case '\0':
  1709.                         state = FINAL_STATE ;        /* found user@host */
  1710.                         break ;
  1711.                     case '@':
  1712.                         state = ERROR_STATE ;        /* user@host@? */
  1713.                         break ;
  1714.                     case '<':
  1715.                         state = LOOK_FOR_FROM ;        /* fromname follows */
  1716.                         break ;
  1717.                     case '$':
  1718.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1719.                         break ;
  1720.                     default:
  1721.                         if (isspace(*cp))
  1722.                             state = AFTER_HOST ;
  1723.                         else
  1724.                             hostlen++ ;
  1725.                 }
  1726.                 break ;
  1727.             case AFTER_HOST:
  1728.                 switch (*cp) {
  1729.                     case '\0':
  1730.                         state = FINAL_STATE ;        /* user@host */
  1731.                         break ;
  1732.                     case '@':
  1733.                         state = ERROR_STATE ;        /* user@host @ */
  1734.                         break ;
  1735.                     case '<':
  1736.                         state = LOOK_FOR_FROM ;        /* user@host < */
  1737.                         break ;
  1738.                     case '$':
  1739.                         state = LOOK_FOR_MSGID ;    /* user@host $ */
  1740.                         break ;
  1741.                     default:
  1742.                         if (!isspace(*cp))
  1743.                             state = ERROR_STATE ;    /* user@host foo */
  1744.                 }
  1745.                 break ;
  1746.             case LOOK_FOR_FROM:
  1747.                 switch (*cp) {
  1748.                     case '\0':                    /* user@host <? */
  1749.                     case '@':                    /* user@host <@ */
  1750.                     case '<':                    /* user@host << */
  1751.                     case '$':                    /* user@host <$ */
  1752.                         state = ERROR_STATE ;
  1753.                         break ;
  1754.                     default:
  1755.                         if (!isspace(*cp)) {
  1756.                             from = cp ;
  1757.                             fromlen++ ;
  1758.                             state = IN_FROM ;
  1759.                         }
  1760.                 }
  1761.                 break ;
  1762.             case IN_FROM:
  1763.                 switch (*cp) {
  1764.                     case '\0':
  1765.                         state = FINAL_STATE ;        /* user@host <foo */
  1766.                         break ;
  1767.                     case '<':
  1768.                         state = ERROR_STATE ;        /* user@host <foo< */
  1769.                         break ;
  1770.                     case '$':
  1771.                         state = LOOK_FOR_MSGID ;    /* message id follows */
  1772.                         break ;
  1773.                     default:
  1774.                         if (isspace(*cp))
  1775.                             state = AFTER_FROM ;
  1776.                         else
  1777.                             fromlen++ ;
  1778.                 }
  1779.                 break ;
  1780.             case AFTER_FROM:
  1781.                 switch (*cp) {
  1782.                     case '\0':
  1783.                         state = FINAL_STATE ;        /* user@host <foo */
  1784.                         break ;
  1785.                     case '@':                        /* user@host <foo @ */
  1786.                     case '<':                        /* user@host <foo < */
  1787.                         state = ERROR_STATE ;
  1788.                         break ;
  1789.                     case '$':
  1790.                         state = LOOK_FOR_MSGID ;    /* user@host <foo $ */
  1791.                         break ;
  1792.                     default:
  1793.                         if (!isspace(*cp))
  1794.                             state = ERROR_STATE ;    /* user@host foo */
  1795.                 }
  1796.                 break ;
  1797.             case LOOK_FOR_MSGID:
  1798.                 if (*cp == '\0')
  1799.                     state = ERROR_STATE ;            /* msgid = $? */
  1800.                 else if (isspace(*cp))
  1801.                     state = ERROR_STATE ;            /* user@host <foo $ bar */
  1802.                 else {
  1803.                     msgid = cp ;
  1804.                     msgidlen++ ;
  1805.                     state = IN_MSGID ;
  1806.                 }
  1807.                 break ;
  1808.             case IN_MSGID:
  1809.                 if (*cp == '\0')
  1810.                     state = FINAL_STATE ;
  1811.                 else if (isspace(*cp))
  1812.                     state = FINAL_STATE ;
  1813.                 else
  1814.                     msgidlen++ ;
  1815.                 break ;
  1816.             default:
  1817.                 /* what are we doing in this state? */
  1818.                 state = ERROR_STATE ;
  1819.         }
  1820.     }
  1821.  
  1822.     if (state == ERROR_STATE)
  1823.         return -1 ;        /* syntax error */
  1824.  
  1825.     if ((m->to = malloc((unsigned)(userlen + hostlen + 2))) == NULLCHAR)
  1826.         return -1 ;        /* no room for to address */
  1827.  
  1828.     strncpy(m->to, user, userlen) ;
  1829.     m->to[userlen] = '\0' ;
  1830.     
  1831.     if (hostlen) {
  1832.         m->to[userlen] = '@' ;
  1833.         strncpy(m->to + userlen + 1, host, hostlen) ;
  1834.         m->to[userlen + hostlen + 1] = '\0' ;
  1835.     }
  1836.  
  1837.     if (fromlen) {
  1838.         if ((m->tofrom = malloc((unsigned)(fromlen + 1))) == NULLCHAR) {
  1839.             free(m->to) ;
  1840.             m->to = NULLCHAR ;
  1841.             return -1 ;
  1842.         }
  1843.         strncpy(m->tofrom, from, fromlen) ;
  1844.         m->tofrom[fromlen] = '\0' ;
  1845.     }
  1846.  
  1847.     if (msgidlen) {
  1848.         if ((m->tomsgid = malloc((unsigned)(msgidlen + 1))) == NULLCHAR) {
  1849.             free(m->to) ;
  1850.             m->to = NULLCHAR ;
  1851.             if (fromlen) {
  1852.                 free(m->tofrom) ;
  1853.                 m->tofrom = NULLCHAR ;
  1854.             }
  1855.             return -1 ;
  1856.         }
  1857.         strncpy(m->tomsgid, msgid, msgidlen) ;
  1858.         m->tomsgid[msgidlen] = '\0' ;
  1859.     }
  1860.     
  1861.     return 0 ;
  1862. }
  1863.  
  1864. /* This opens the data file and writes the mail header into it.
  1865.  * Returns 0 if OK, and -1 if not.
  1866.  */
  1867.  
  1868. static
  1869. mbx_data(m)
  1870. struct mbx *m ;
  1871. {
  1872.     time_t t, time() ;
  1873.     char *ptime() ;
  1874.     extern char hostname[] ;
  1875.     extern FILE *tmpfile();
  1876.     extern long get_msgid() ;
  1877.     
  1878.     if ((m->tfile = tmpfile()) == NULLFILE)
  1879.         return -1 ;
  1880.  
  1881.     time(&t) ;
  1882.     fprintf(m->tfile,"Date: %s",ptime(&t)) ;
  1883.     if (m->tomsgid)
  1884.         fprintf(m->tfile, "Message-Id: <%s@%s>\n", m->tomsgid, hostname) ;
  1885.     else
  1886.         fprintf(m->tfile,"Message-Id: <%ld@%s>\n",get_msgid(),hostname) ;
  1887.     fprintf(m->tfile,"From: %s%%%s.bbs@%s\n",
  1888.             m->tofrom ? m->tofrom : m->name, m->name, hostname) ;
  1889.     fprintf(m->tfile,"To: %s\n",m->to) ;
  1890.     fprintf(m->tfile,"Subject: %s\n",m->line) ;
  1891.     if (m->stype != ' ')
  1892.         fprintf(m->tfile,"X-BBS-Msg-Type: %c\n", m->stype) ;
  1893.     fprintf(m->tfile,"\n") ;
  1894.     
  1895.     return 0 ;
  1896. }
  1897.  
  1898. /* Shut down the mailbox communications connection */
  1899.  
  1900. static void
  1901. mbx_disc(m)
  1902. struct mbx *m ;
  1903. {
  1904.     switch (m->type) {
  1905.       case MBX_AX25:
  1906.         disc_ax25(m->cb.ax25_cb) ;
  1907.         break ;
  1908.       case MBX_NETROM:
  1909.           disc_nr4(m->cb.nr4_cb) ;
  1910.         break ;
  1911.     }
  1912. }
  1913. #endif /* XOBBS */
  1914.